"""
Game.py

Author: Miles Malerba
Date: 9-20-08
"""

from MakerMove import MakerMove
from Observable import Observable

class Game(Observable):
    """represents a game of mastermind. keeps track of all moves,
       allows moves to be made or undone, notifies observers when a move
       is made or undone.
    """

    #possible player turn states
    BREAKER_TURN = 0
    MAKER_TURN = 1

    #possible win sates
    NO_WIN = 0
    BREAKER_WIN = 1
    MAKER_WIN = 2

    #types of notifications
    NOTIFY_MOVE = 0
    NOTIFY_UNDO = 1
    
    def __init__(self):
        """constructor. initializes move stack, turn, and last undo"""
        Observable.__init__(self)
        self.move_stack = []
        self.turn = self.BREAKER_TURN
        self.last_undo = None

    def make_move(self, move):
        """takes a game move object and adds it to the move stack.
           also changes turn state appropriately and notifies observers
        """
        if self.get_winner() == self.NO_WIN:
            self.move_stack.append(move)
        
            if self.turn == self.BREAKER_TURN:
                self.turn = self.MAKER_TURN
            elif self.turn == self.MAKER_TURN:
                self.turn = self.BREAKER_TURN
                
            self.notify_observers(self.NOTIFY_MOVE)

    def undo_last_move(self):
        """undoes the last move that was made and saves it in last_undo.
           also changes the turn state appropriately and notifies observers
        """
        if len(self.move_stack) > 0:
            self.last_undo = self.move_stack.pop()
            
            if self.turn == self.BREAKER_TURN:
                self.turn = self.MAKER_TURN
            elif self.turn == self.MAKER_TURN:
                self.turn = self.BREAKER_TURN
                
            self.notify_observers(self.NOTIFY_UNDO)

    def get_winner(self):
        """determines if there is a winner to this game yet.
           returns BREAKER_WIN, MAKER_WIN, or NO_WIN
        """
        if len(self.move_stack) > 0 and self.move_stack[-1].get_player() == 'Maker':
            all_black = True
            for piece in self.move_stack[-1].get_pieces():
                if piece != MakerMove.BLACK:
                    all_black = False
                    break
            if all_black:
                return self.BREAKER_WIN
        if len(self.move_stack) == 20:
            return self.MAKER_WIN
        return self.NO_WIN

    def get_turn(self):
        """gets whose turn it is. returns MAKER_TURN or BREAKER_TURN"""
        return self.turn

    def get_last_undo(self):
        """gets last move that was undone"""
        return self.last_undo

    def get_move_stack(self):
        """gets the stack containing all moves made so far"""
        return self.move_stack

    def get_last_move(self):
        """gets the last move that was made"""
        if len(self.move_stack) == 0:
            return None
        return self.move_stack[len(self.move_stack)-1]
